package cn.tedu.v6;

import java.io.*;
import java.net.BindException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.*;

/**
 * version 6 在线用户列表
 */

public class Server {
    private ServerSocket serverSocket;
    private static final Integer PORT=4545;
    private List<PrintWriter> allOut=new ArrayList<>();

    //1.私有化集合保存所有用户名 --onlineUsers
    private List<String> onlineUsers=new ArrayList<>();

    private Map<String,String> userDateBase;
    public Server() {
        try {
            serverSocket = new ServerSocket(PORT);

            userDateBase=new HashMap<>();
            userDateBase.put("海燕","123456");
            userDateBase.put("希奥包","654123");
        } catch (BindException e) {
            System.out.println("端口号重复申请，建议换个端口号");
        } catch (IOException e) {
            System.out.println("申请端口号失败~~~");
        }
    }

    public void start() {
        try {
            while (true) {
                System.out.println("----等待用户端链接---");
                Socket socket = serverSocket.accept();
                new Thread(new ClientHandler(socket)).start();
            }
        } catch (IOException e) {
            System.out.println("服务器端通讯断开了");
        } finally {

            if (serverSocket!=null&&!serverSocket.isClosed()){
                try {
                    serverSocket.close();
                } catch (IOException e) {
                    System.out.println("服务器关闭失败");
                }
            }

        }
    }


    public static void main(String[] args)  {
        new Server().start();
    }




    private synchronized void  broadcastMessage(String message){
        for (PrintWriter pw:allOut){
            pw.println("消息广播："+message);

        }
    }
    //2.封装方法：同步转发给所有客户端消息：“在线用户：”+username
    //updateOnlineUser  更新在线人数的方法：“在线用户：”+username
    //字符串：String userList="在线用户"+String.join("、",onlineUser)
    //userList 写出给所有客户端
    private synchronized void updateOnlineUsers(String userList){
       for (String pw:onlineUsers){
           userList="在线用户："+String.join("、",onlineUsers);
       }
       broadcastMessage(userList);
    }
    private class ClientHandler implements Runnable {
        private Socket socket;
        private String ip;
        private BufferedReader br;
        private PrintWriter pw;

        private String username;
        private String password;
        public ClientHandler(Socket s){
            this.socket=s;
            ip=socket.getInetAddress().getHostAddress();

            try {
                br = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF8"));
                pw=new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), "UTF8")), true);

                synchronized (allOut) {
                    allOut.add(pw);
                }
            } catch (IOException e) {
                System.out.println("客户端断开通讯");
            }

        }

        private boolean Login(String user,String pass){

            return userDateBase.containsKey(user)&&userDateBase.get(user).equals(pass);
        }

        private void handlerChat(){
            new Thread(()->{
                try {
                    String message;
                    while ((message=br.readLine())!=null) {
                        System.out.println("客户端说："+message);
                        System.out.println("服务器端请输入：");
                        broadcastMessage(message);
                    }
                } catch (IOException e) {
                    System.out.println("客户端读入失败了");
                }
            }).start();

            Scanner input = new Scanner(System.in);
            while (true) {
                System.out.println("服务器请输入：");
                String say=input.nextLine();
                pw.println("服务器说："+say);
            }
        }
        public void run() {
            try {

                pw.println("请输入用户名：");
                username=br.readLine();

                pw.println("请输入密码：");
                password=br.readLine();


                if (Login(username,password)){
                    pw.println("登录成功，欢迎进入聊天室");
                   //3.所有用户添加至集合【同步块：登陆集合】
                    // 3.1转发在线用户方法
                        synchronized (onlineUsers){
                            onlineUsers.add(username);
                            updateOnlineUsers(username);
                        }
                        handlerChat();

                }else{
                    pw.println("登陆失败，用户名或者密码错误");
                    socket.close();
                }

                } catch(NullPointerException e){
                    System.out.println("IO流传入对象，有对象为null,立马核对，建议：查看try块中对象可能赋值为null");
                } catch (IOException e){
                     System.out.println("服务器端断开连接");
                 } finally{
                    //4.客户端断开连接，移除当前集合【同步】
                synchronized (onlineUsers){
                    onlineUsers.remove(pw);
                }
                    synchronized (allOut){
                        allOut.remove(pw);
                    }
                    if (br != null)
                        try {
                            br.close();
                        } catch (IOException e) {
                            System.out.println("结束通讯：关闭失败");
                        }
                    if (pw!=null) pw.close();
                    if (socket!=null&&!socket.isClosed()){
                        try {
                            socket.close();
                        } catch (IOException e) {
                            System.out.println("通讯关闭失败");
                        }
                    }
                }
            }
        }
    }


